/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package at.fhj.refactor.refactorings.postgres;

import at.fhj.itm.generator.ColumnValueMapping;
import at.fhj.itm.generator.ColumnValuePair;
import at.fhj.itm.generator.SqlCodeGenerator;
import at.fhj.itm.metadata.Column;
import at.fhj.itm.metadata.Constraint;
import at.fhj.itm.metadata.DepdendencyProvider;
import at.fhj.itm.metadata.ForeignKeyConstraint;
import at.fhj.itm.metadata.Index;
import at.fhj.itm.metadata.MetadataItem;
import at.fhj.itm.metadata.Sequence;
import at.fhj.itm.metadata.Table;
import at.fhj.itm.metadata.impl.postgres.PostgresCheckConstraint;
import at.fhj.itm.metadata.impl.postgres.PostgresColumn;
import at.fhj.itm.metadata.impl.postgres.PostgresConstraint;
import at.fhj.itm.metadata.impl.postgres.PostgresForeignKey;
import at.fhj.itm.metadata.impl.postgres.PostgresIndex;
import at.fhj.itm.metadata.impl.postgres.PostgresSequence;
import at.fhj.itm.metadata.impl.postgres.PostgresSqlDataType;
import at.fhj.itm.metadata.impl.postgres.PostgresTable;
import at.fhj.itm.refactor.DataRefactoring;
import at.fhj.itm.refactor.RefactorException;
import at.fhj.itm.refactor.report.RefactoringReport;
import at.fhj.itm.refactor.report.ReportItem;
import at.fhj.itm.refactor.report.ReportSeverity;
import at.fhj.refactor.refactorings.SplitTable;

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.jar.Attributes.Name;

import javax.swing.RowFilter;

import org.apache.velocity.runtime.log.Log;


/**
 *
 * @author Seuchter
 */
public class PostgresSplitTable implements SplitTable {

    public static final String PRIMARY_KEY_DATATYPE_NAME = "integer";
    public static final String SEQUENCE_COL_DEFAULT_TEMPLATE = "nextval('%s'::regclass)";
    public static final String SEQ_NAME_TEMMPLATE = "seq_%s_%s";
    private static final String PK_NAME_TEMPLATE = "pk_%s_%s";
    private PostgresTable table;

    private String tableNameLeft;
    private String tableNameRight;
    private String rightTablePrimaryKeyColumn;
    private String rightTablePrimaryKeyName;
    private String foreignKey;
    private boolean rightTablePrimaryKeyAutoIncrement;
    private String referencingColumn;
    private PostgresColumn splitReferenceColumn;
    private List<PostgresColumn> columnsRight;
    private List<PostgresColumn> columnsLeft;
    private List<PostgresTable> generatedTable;
    private List<PostgresSequence> generatedSequences;
    private PostgresSequence leftTableSequence;
    private PostgresSequence rightTableSequence;
    private DepdendencyProvider dependencyProvider;
    private boolean refactoringPrepared;
    private PostgresTable rightTable;
    private List<ReportItem> refactoringReportItems;
    
    public PostgresSplitTable(DepdendencyProvider depProvider) {
        this.dependencyProvider = depProvider;
        generatedSequences = new ArrayList<PostgresSequence>();
        generatedTable = new ArrayList<PostgresTable>();
    }

    private void resetRefactoringMetadata() {
        generatedTable = new ArrayList<PostgresTable>();
        generatedSequences = new ArrayList<PostgresSequence>();
        refactoringPrepared = false;
    }

    @Override
	public PostgresTable getTable() {
        return table;
    }

    public String getTableNameRight() {
        return tableNameRight;
    }

    public String getRightTablePrimaryKeyName() {
        return rightTablePrimaryKeyName;
    }

    public void setRightTablePrimaryKeyName(String name) {
        if(!name.trim().isEmpty()){
        	rightTablePrimaryKeyName = name;
        }
    	
    }

    public String getTableNameLeft() {
        return tableNameLeft;
    }

    @Override
	public boolean hasRightTablePrimaryKeyAutoincrement() {
        return rightTablePrimaryKeyAutoIncrement;
    }

    @Override
	public void setRightTablePrimaryKeyAutoincrement(boolean autoIncrement) {
        this.rightTablePrimaryKeyAutoIncrement = autoIncrement;
    }

    public void setTableNameLeft(final String tableNameLeft) {
        if(!tableNameLeft.trim().isEmpty()){
        	this.tableNameLeft = tableNameLeft;
        }
    	
    }

    public void setTableNameRight(String tableNameRight) {
        if(!tableNameRight.trim().isEmpty()){
        	this.tableNameRight = tableNameRight;
        }
    	
    }


	@Override
	public String getRightTablePrimaryKeyColumnName() {

        if (rightTablePrimaryKeyColumn == null) {
            return "id";
        }

        return rightTablePrimaryKeyColumn;
    }

    @Override
	public void setRightTablePrimaryKeyColumnName(String name) {
        if(!name.trim().isEmpty()){
        	this.rightTablePrimaryKeyColumn = name;
        }
    	
    }

    public String getForeignKeyName() {

        if (foreignKey == null) {
            if (tableNameRight != null && tableNameLeft != null) {
                return "fk_" + tableNameLeft + "_" + tableNameRight;
            }

        }

        return foreignKey;
    }

    public void setForeignKeyName(String leftTableNameForeignKey) {
        if(!leftTableNameForeignKey.trim().isEmpty()){
        	this.foreignKey = leftTableNameForeignKey;
        }
    	
    }

    public RefactoringReport validateParamters() {
        List<ReportItem> report = new ArrayList<ReportItem>();
        if (table == null) {
            report.add(new ReportItem(ReportSeverity.ERROR,
                    "Missing paramater: table", "A required parameter is missing."));
        }
        if (tableNameLeft == null) {
            report.add(new ReportItem(ReportSeverity.ERROR,
                    "Missing paramater: table name left ", "A required parameter is missing."));
        }
        if (tableNameRight == null) {
            report.add(new ReportItem(ReportSeverity.ERROR,
                    "Missing paramater: table name right ", "A required parameter is missing."));
        }
        if (columnsLeft == null || columnsLeft.isEmpty()) {
            report.add(new ReportItem(ReportSeverity.ERROR,
                    "Missing paramater: left columns ", "A required parameter is missing."));
        }
        if (columnsRight == null || columnsRight.isEmpty()) {
            report.add(new ReportItem(ReportSeverity.ERROR,
                    "Missing paramater: right columns ", "A required parameter is missing."));
        }

        if(hasRightTablePrimaryKeyAutoincrement()){
        	String message = String.format("Generating sequence '%s' in order to emulate autoincrement behavour",
			String.format(SEQ_NAME_TEMMPLATE, getTableNameRight(), getRightTablePrimaryKeyColumnName()));
        	
        	report.add(new ReportItem(ReportSeverity.INFORMATION, 
        			"Implicit sequence generation",message));
        }
        
        report.addAll(checkConstraints(getTable().getColumns()));
        report.addAll(checkIndices(getTable().getColumns()));
        return new RefactoringReport(report);
    }

    public List<PostgresColumn> getColumnsLeft() {
        return columnsLeft;
    }

    public List<PostgresColumn> getColumnsRight() {
        return columnsRight;
    }

    public void setColumnLeft(List<? extends Column> columns) {
        this.columnsLeft = (List<PostgresColumn>) columns;
    }

    public void setColumnsRight(List<? extends Column> columns) {
        this.columnsRight = (List<PostgresColumn>) columns;
    }

    public String getReferencingColumnName() {
        if (referencingColumn == null && tableNameRight != null) {
            return "id_" + tableNameRight;
        }

        return referencingColumn;
    }

    public void setReferencingColumnName(String columnName) {
        if(!columnName.trim().isEmpty()){
        	this.referencingColumn = columnName;

        }
    }

    public String generateRefactoringScript(SqlCodeGenerator generator) {
        StringBuilder sb = new StringBuilder();

        for(PostgresSequence curSeq : generatedSequences){
            sb.append(generator.generateSequence(curSeq)).append("\n");
        }

        for(PostgresTable curTable : generatedTable){
            sb.append(generator.generateTable(curTable)).append("\n");

        }
        sb.append(generator.generateForeignKeyConstraints(generatedTable));
        return sb.toString();

    }

    public String generateDataMigrationScript() {
        return null;
    }

    private List<ReportItem> checkConstraints(List<PostgresColumn> tableColumns) {
        PostgresTable originalTable = getTable();
        List<ReportItem> reportItems = new ArrayList<ReportItem>();

        for (PostgresConstraint curCons : originalTable.getConstraints()) {
            if (curCons.getConstraintColumns().size() > 1) {
                if (!tableColumns.containsAll(curCons.getConstraintColumns())) {
                    reportItems.add(new ReportItem(ReportSeverity.ERROR,
                            "Splited Constraint",
                            String.format("Refactoring would split constraint '%s' over both tables",
                            curCons.getName())));
                }
            }
        }

        return reportItems;
    }

    private List<ReportItem> checkIndices(List<PostgresColumn> tableColumns) {
        PostgresTable originalTable = getTable();
        List<ReportItem> reportItems = new ArrayList<ReportItem>();

        for (PostgresIndex curInd : originalTable.getIndices()) {
            if (curInd.getColumns().size() > 1) {
                if (!tableColumns.containsAll(curInd.getColumns())) {
                    reportItems.add(new ReportItem(ReportSeverity.ERROR,
                            "Splited index",
                            String.format("Refactoring would split index '%s' over both tables",
                            curInd.getName())));
                }
            }
        }

        return reportItems;
    }

    private PostgresConstraint findPrimaryKey(PostgresTable table){
        for(PostgresConstraint c : table.getConstraints()){
           if(c.getConstraintType().equals(Constraint.CONSTRAINT_TYPE_PRIMARY_KEY)){
               return c;
           }
        }
        return  null;
    }
    private PostgresColumn generateRightTablePrimaryKeyColumn(PostgresTable tableRight) {

        String columnDefaultValue = null;

        if (rightTablePrimaryKeyAutoIncrement) {
            String seqName = String.format(SEQ_NAME_TEMMPLATE, tableRight.getName(), getRightTablePrimaryKeyColumnName());
            PostgresSequence seq = new PostgresSequence(seqName);
            columnDefaultValue = String.format(SEQUENCE_COL_DEFAULT_TEMPLATE, seq.getName());
            generatedSequences.add(seq);
            rightTableSequence = seq;
        }
		
        PostgresColumn col = new PostgresColumn(1, getRightTablePrimaryKeyColumnName(), false,
                new PostgresSqlDataType(PRIMARY_KEY_DATATYPE_NAME), columnDefaultValue,true,false);
        
        String constraintName = String.format(PK_NAME_TEMPLATE, tableRight.getName(),
                col.getName());
        
        PostgresConstraint constraint = new PostgresConstraint(-1,
                constraintName, Arrays.asList(col), PostgresConstraint.CONSTRAINT_TYPE_PRIMARY_KEY);
        
        tableRight.getConstraints().add(constraint);
        logCreateColumnRefactorStep(tableRight,col);
        logCreateConstraint(constraint);
        return col;


    }
    
    private void logCreateRefactorCreateStep(Table table){
    	ReportItem item = ReportItem.createRefactoringStep("Create Table", 
    			String.format("Creating Table '%s'",table.getName()));
    	refactoringReportItems.add(item);
    }
    private void logCreateColumnRefactorStep(Table parentTable, Column col){
    	ReportItem item = ReportItem.createRefactoringStep("Create Column", 
    			String.format("Creating column '%s' in table '%s'",col.getName(),parentTable.getName()));
    	refactoringReportItems.add(item);
    }
    private void logRefactorColumn(Table baseTable, Column baseCol, Table newTable, Column newColumn)
    {
    	ReportItem item = ReportItem.createRefactoringStep("Moving Column",
    			String.format("Move column '%s' from table '%s' to '%s'", baseCol.getName(), baseTable.getName(),
    					newTable.getName()));
    	refactoringReportItems.add(item);
    }
    private void logRefactorIndexStep(Index oldIndex, Index newIndex){
    	ReportItem item = ReportItem.createRefactoringStep("Refactoring Index",
    			String.format("Creating index '%s' based on index '%s'" , oldIndex, newIndex));
    	refactoringReportItems.add(item);
    }
    private void logRefactorConstraintStep(Constraint oldCons, Constraint newCons){
    	ReportItem item = ReportItem.createRefactoringStep("Refactoring constraint", 
    			String.format("Creating constraint '%s' of type '%s' based on constraint '%s' '", 
    					newCons.getName(), newCons.getConstraintType(), oldCons.getName()));
    	refactoringReportItems.add(item);
    }
    private void logCreateConstraint(Constraint cons){
    	ReportItem item = ReportItem.createRefactoringStep("Create constraint", String.format("Creating constraint '%s' of type '%s'", 
    			cons.getName(), cons.getConstraintType()));
    	refactoringReportItems.add(item);
    }
    protected PostgresTable generateRightTableMetadata() {
        
    	
    	PostgresTable rightTable = new PostgresTable(-1, getTableNameRight(), getTable().getOwner().copy());
        List<PostgresColumn> cols = new ArrayList<PostgresColumn>();
        logCreateRefactorCreateStep(rightTable);

        
        cols.add(generateRightTablePrimaryKeyColumn(rightTable));
  
        for (int i = 0; i < columnsRight.size(); i++) {
            PostgresColumn newColumn = refactorColumn(rightTable, columnsRight.get(i), i + 2);
            cols.add(newColumn);
            logRefactorColumn(getTable(), columnsRight.get(1), rightTable, newColumn);
        }

        rightTable.setColumns(cols);

        List<PostgresIndex> indices = refactorIndices(rightTable);
        rightTable.setIndices(indices);
        List<PostgresConstraint> constraints = refactorConstraints(rightTable);
        rightTable.setConstraints(constraints);
        return rightTable;
    }

    protected PostgresTable generateLeftTableMetadata() {
        PostgresTable leftTable = new PostgresTable(-1, getTableNameLeft(), getTable().getOwner().copy());

        logCreateRefactorCreateStep(leftTable);

        List<PostgresColumn> cols = new ArrayList<PostgresColumn>();
        for (int i = 0; i < columnsLeft.size(); i++) {
            PostgresColumn curCol = refactorColumn(leftTable, columnsLeft.get(i), i);
            cols.add(curCol);
            logRefactorColumn(getTable(), columnsLeft.get(i), 
            		leftTable, curCol);

        }
        
        PostgresConstraint orginalPrimarykey = findPrimaryKey(getTable());
        List<PostgresColumn> primaryKeyColumns = new ArrayList<PostgresColumn>();
        
        for(PostgresColumn curCol : orginalPrimarykey.getConstraintColumns()){
            primaryKeyColumns.add(findMetadataByName(cols, curCol.getName()));
            logCreateColumnRefactorStep(leftTable, curCol);
        }
        
        
        
        String pkName = String.format(PK_NAME_TEMPLATE, leftTable.getName(),primaryKeyColumns.get(0).getName());
        PostgresConstraint newPk = new PostgresConstraint(-1, pkName,
                primaryKeyColumns,Constraint.CONSTRAINT_TYPE_PRIMARY_KEY);
        logCreateConstraint(newPk);
        PostgresColumn locationColumn = new PostgresColumn(cols.size()+1,
                getReferencingColumnName(), true, new PostgresSqlDataType("int4") , null);


        PostgresColumn foreignColumn = rightTable.getColumns().get(0);
        splitReferenceColumn = locationColumn;
        logCreateColumnRefactorStep(leftTable, foreignColumn);
        PostgresForeignKey locationConstraint = new PostgresForeignKey(1,getForeignKeyName(),
                ForeignKeyConstraint.CONSTRAINT_ACTION_NONE, ForeignKeyConstraint.CONSTRAINT_ACTION_NONE,
                false,false,Arrays.asList(foreignColumn),Arrays.asList(locationColumn),rightTable);
                
        cols.add(locationColumn);
        
        leftTable.setColumns(cols);
        List<PostgresIndex> indices = refactorIndices(leftTable);
        List<PostgresConstraint> constraints = refactorConstraints(leftTable);
        constraints.add(0, newPk);
        constraints.add(locationConstraint);
        leftTable.setIndices(indices);
        leftTable.setConstraints(constraints);


        return leftTable;


    }

    protected List<PostgresConstraint> refactorConstraints(PostgresTable targetTable) {
        PostgresTable originalTable = getTable();
        Set<String> refactoredConstraints = new HashSet<String>();
        List<PostgresConstraint> constraints = new ArrayList<PostgresConstraint>();
        for (PostgresConstraint curConstraint : originalTable.getConstraints()) {


            String name = curConstraint.getName() + "_refactored";
            if (targetTable.getColumns().containsAll(curConstraint.getConstraintColumns())) {
                List<PostgresColumn> constraintColumns = new ArrayList<PostgresColumn>();

                for (PostgresColumn curCol : curConstraint.getConstraintColumns()) {
                    PostgresColumn newCol = findMetadataByName(targetTable.getColumns(), curCol.getName());
                    constraintColumns.add(newCol);
                }

                PostgresConstraint newConstraint = null;

                if(curConstraint instanceof PostgresForeignKey){
                    PostgresForeignKey curFk = (PostgresForeignKey) curConstraint;
                    PostgresForeignKey fk = new PostgresForeignKey(-1, name, curFk.getUpdateAction(),
                            curFk.getDeleteAction(), curFk.isDefereable(), curFk.isInitialyDefered(),curFk.getReferencingColumns(),
                            constraintColumns,
                            curFk.getReferencingTable());

                    newConstraint = fk;

                }
                else if(curConstraint instanceof PostgresCheckConstraint)
                {
                    PostgresCheckConstraint curCheck = (PostgresCheckConstraint) curConstraint;
                    PostgresCheckConstraint newCheck = new PostgresCheckConstraint(-1, name, curCheck.getConstraintColumns(),
                            curCheck.getCheckExpression());
                    newConstraint = newCheck;
                }
                else {
                    newConstraint = new PostgresConstraint(-1, name, constraintColumns, curConstraint.getConstraintType());
                }

                if(newConstraint.getConstraintType().equals(Constraint.CONSTRAINT_TYPE_PRIMARY_KEY)){
                    continue;
                }

                boolean skip = !refactoredConstraints.add(newConstraint.getName());
                if(!skip){
                    constraints.add(newConstraint);
                }
                
                logRefactorConstraintStep(curConstraint, newConstraint);


            }




        }
        return constraints;

    }


    private String getUnderscoreSeperatedString(List<? extends MetadataItem> items){
        StringBuilder sb = new StringBuilder();

        for(int i = 0; i < items.size(); i++){
            sb.append(items.get(i).getName());
            if(i != (items.size()-1)){
                sb.append("_");
            }
        }
        
        return sb.toString();
    }

    private String renameMetadataItemGeneric(MetadataItem item){
    	return item + "_refactored";
    }
    
    protected List<PostgresIndex> refactorIndices(PostgresTable targetTable) {
        PostgresTable originalTable = getTable();
        Set<String> refactoredIndices = new HashSet<String>();
        List<PostgresIndex> indices = new ArrayList<PostgresIndex>();
        for (PostgresIndex curIndex : originalTable.getIndices()) {

            if(curIndex.isPrimaryKey()){
                continue;
            }

            if(curIndex.isUnique()){
                continue;
            }

            if (targetTable.getColumns().containsAll(curIndex.getColumns())) {
                List<PostgresColumn> indexColumns = new ArrayList<PostgresColumn>();
                for (PostgresColumn curCol : curIndex.getColumns()) {
                    PostgresColumn newCol = findMetadataByName(targetTable.getColumns(), curCol.getName());
                    indexColumns.add(newCol);

                }

                String indexName = renameMetadataItemGeneric(curIndex);

                PostgresIndex newIndex = new PostgresIndex(indexName,
                        curIndex.isPrimaryKey(), curIndex.isClustered(), curIndex.isUnique(),
                        curIndex.getAccessMethod(), indexColumns, targetTable);

                


                boolean skip = !refactoredIndices.add(curIndex.getName());

                if (!skip) {
                    indices.add(newIndex);
                }



            }

        }
        System.out.println();
        return indices;
    }

    private <T extends MetadataItem> T findMetadataByName(List<T> metadata, String name) {
        for (MetadataItem curItem : metadata) {
            if (curItem.getName().equals(name)) {
                return (T) curItem;
            }
        }
        return null;
    }

    protected PostgresColumn refactorColumn(PostgresTable table, PostgresColumn column, int index) {

        PostgresSequence seq = (PostgresSequence) dependencyProvider.getDependingSequences(getTable(), column);




        if (seq != null) {
        	PostgresSequence newSequence = seq.copy();
        	
            newSequence.setName(String.format(SEQ_NAME_TEMMPLATE, table.getName(),
                    column.getName()));
            generatedSequences.add(newSequence);
        }

        
        
        

        String columnDefaultValue = column.getDefaultValue();

        if (seq != null) {
            columnDefaultValue = String.format(SEQUENCE_COL_DEFAULT_TEMPLATE, seq.getName());
        }


        PostgresColumn newCol = new PostgresColumn(index, column.getName(),
                column.isNotNull(), (PostgresSqlDataType) column.getColumnType(), columnDefaultValue);

        return newCol;

    }

    @Override
	public void setTable(Table table) {
        if (!(table instanceof PostgresTable)) {
            throw new IllegalArgumentException("Invalid implementation");
        }
        this.table = (PostgresTable) table;
    }

    public RefactoringReport prepareRefactoring() {
        resetRefactoringMetadata();
        refactoringReportItems = new ArrayList<ReportItem>();
        PostgresTable tableRight = generateRightTableMetadata();
        this.rightTable = tableRight;
        PostgresTable tableLeft = generateLeftTableMetadata();
        
        PostgresSequence pkSequence = (PostgresSequence) dependencyProvider.getDependingSequences(getTable(), getTable().getColumns().get(0));
        if(pkSequence != null){
        	if(hasRightTablePrimaryKeyAutoincrement()){
        		leftTableSequence = generatedSequences.get(1);
        	}
        	else {
				leftTableSequence = generatedSequences.get(0);
			}
        }

        generatedTable.add(tableLeft);
        generatedTable.add(tableRight);
        
        
        refactoringPrepared = true;
        return new RefactoringReport(refactoringReportItems);
    }

    
    private ColumnValueMapping<Column, String> createLeftMapping(){
    	PostgresTable leftTable = generatedTable.get(0);
    	boolean leftTableAutoIncrement = dependencyProvider.getDependingSequences(getTable(), 
    			getTable().getColumns().get(0)) != null;
    	ColumnValueMapping<Column, String> mapping = new ColumnValueMapping<Column, String>();
    	
    	
    	for(PostgresColumn column : generatedTable.get(0).getColumns()){
    		//we don't to map the id value since the value is auto generated 
    		if(column.isPrimaryKeyColumn() && leftTableAutoIncrement){
    			continue;
    		}
    		else if(column == splitReferenceColumn){
    			mapping.addMapping(column, null,false);
    			if(hasRightTablePrimaryKeyAutoincrement()){

    	    		mapping.updateBinding(column.getName(),String.format("currval('%s'::regclass)", rightTableSequence.getName()));
    	    	}
    		}
    		else{
    				mapping.addMapping(column, null);
    		}
    	
    		
    	}
    
    	
    	return mapping;
    }
    private ColumnValueMapping<Column, String> createRightMapping(){
    	PostgresTable rightTable = generatedTable.get(1);
    	ColumnValueMapping<Column, String> mapping = new ColumnValueMapping<Column, String>();
    	for(PostgresColumn column: rightTable.getColumns()){
    		
    		if(column.isPrimaryKeyColumn() && hasRightTablePrimaryKeyAutoincrement()){
    			continue;
    		}
    		mapping.addMapping(column, null);
    	}
    	
    	return mapping;
    }
    private void applyResultToMapping(ColumnValueMapping<Column, String> mapping, 
    		ResultSet set)throws SQLException{
    	for(ColumnValuePair<Column, String>  pair : mapping.getMapping()){
    		PostgresColumn column = (PostgresColumn) pair.getColumn();
    		//the pk column is part of the mapping meaning that there is no sequence associated
    		//the id value has to be generated separtly and can't be taken from the result set
    		if(column.isPrimaryKeyColumn()){
    			continue;
    		}
    		try{
        		String newValue = set.getString(pair.getColumn().getName());
        		pair.setValue(newValue);
        		
    		}catch (SQLException e) {
				//TODO: find a better way to test if column is in a result set
			}

    		
    	}
    }
	@Override
	public void generateDataRefactoringSqlScript(Writer scriptWriter, SqlCodeGenerator generator)
			throws IOException {
	
		try{
			BufferedWriter writer = new BufferedWriter(scriptWriter);		
			Connection connection = dependencyProvider.getConnection();
			Statement queryStmt = connection.createStatement();
			ResultSet set = queryStmt.executeQuery(String.format("SELECT * FROM \"%s\"", getTable().getName()));
			ColumnValueMapping<Column, String> leftMapping = createLeftMapping();
			ColumnValueMapping<Column, String> rightMapping = createRightMapping();
			PostgresTable leftTable = generatedTable.get(0);
			PostgresTable rightTable = generatedTable.get(1);
			boolean leftTableHasSequence = leftTableSequence != null;
			
			
			int pkLeft = 1;
			int pkRight = 1;
			while(set.next()){
				applyResultToMapping(rightMapping, set);
				applyResultToMapping(leftMapping, set);
			
				if(!hasRightTablePrimaryKeyAutoincrement()){
					rightMapping.updateBinding(rightTable.getColumns().get(0).getName(),
							new Integer(pkRight).toString());
					leftMapping.updateBinding(splitReferenceColumn.getName(), new Integer(pkRight).toString());
					
					if(!leftTableHasSequence){
						leftMapping.getMapping().get(0).setValue(new Integer(pkLeft).toString());
					}
							
				}
				writer.append(generator.generateInsertStatement(rightTable, rightMapping));
				writer.newLine();
				writer.append(generator.generateInsertStatement(leftTable, leftMapping));
				writer.newLine();
				pkLeft++;
				pkRight++;
			}
			writer.flush();
			
			
			
		}
		catch(SQLException ex){
			throw new RefactorException("Error while migrating data", ex);
		}
		catch(IOException ex){
			throw new RefactorException("Error while migrating data", ex);
		}
	
		
		
		
		
	}



}
